<?php
namespace app\workerman\controller;

use app\common\controller\Api;
use fast\Random;
use GatewayWorker\Lib\Gateway;
use think\Config;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;

class WorkerEvents extends Api
{
    /**
     * 当客户端连接时触发
     * 如果业务不需此回调可以删除onConnect
     * @param $client_id
     */
    public static function onConnect($client_id)
    {
        // 向所有人发送
        // 向当前client_id发送数据
//        var_dump($this->auth->id);
        Gateway::sendToClient($client_id, "Hello $client_id");
//        Gateway::sendToAll("$client_id login\r\n");
    }

    /**
     * 当客户端发来消息时触发
     * @param $client_id
     * @param $message
     * @return false|void
     * @throws DbException
     * @throws Exception
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public static function onMessage($client_id, $message)
    {
        $msg_data = json_decode($message, true);
        if(!isset($msg_data['token'])){
            $msg=[
                'msg'=>'你谁鸭！',
            ];
            $msg=json_encode($msg);
            Gateway::sendToClient($client_id, $msg);
            return;
        }
        $userInfo=\app\common\library\Token::get($msg_data['token']);
        if(!$userInfo){
            $msg=[
                'msg'=>'你谁鸭！',
            ];
            $msg=json_encode($msg);
            Gateway::sendToClient($client_id, $msg);
            return;
        }
        $user=Db::name('user')->where('id',$userInfo['user_id'])->find();
        //判断发送类型
        switch ($msg_data['type']) {
            case 'ping':
                $msg=[
                    'msg'=>'我在',
                ];
                $msg=json_encode($msg);
                Gateway::sendToClient($client_id, $msg);
                break;
            case 'bind':
                //绑定
                Gateway::bindUid($client_id, $user['id']);
                break;
            case 'add':
                //主持人开始对局
                $role=explode(',',$msg_data['role_list']);
                if(count($role)!=$msg_data['number']){
                    $msg=[
                        'type'=>'error',
                        'msg'=>'人数与角色数量不同',
                    ];
                    $msg=json_encode($msg);
                    Gateway::sendToClient($client_id, $msg);
                }
                $id=Db::name('room')->insertGetId([
                    'user_id'=>$user['id'],
                    'room_group'=>WorkerEvents::getGroup(),
                    'number'=> $msg_data['number'],
                    'role_list'=>$msg_data['role_list'],
                    'createtime'=>time(),
                ]);
                $msg=[
                    'type'=>'success',
                    'room_id'=>$id,
                    'msg'=>'成功',
                ];
                $msg=json_encode($msg);
                Gateway::sendToClient($client_id, $msg);
                //主持人加入房间
                Gateway::joinGroup($client_id, $id);
                break;
            case 'join':
                //绑定群组
                Gateway::joinGroup($client_id, $msg_data['room_id']);
                //几号位
//                $room_num=Db::name('game')->where('room_id',$msg_data['room_id'])->count();
                //通知群组
                if($user['group_id']=='1'){
                    $dd=Db::name('game')->where('user_id',$user['id'])->where('room_id',$msg_data['room_id'])
                        ->find();
                    if(!$dd){
                        //加入房间
                        Db::name('game')->insert([
                            'user_id'=>$user['id'],
                            'room_id'=>$msg_data['room_id'],
                            'createtime'=>time()
                        ]);
                    }
                    $msg=[
                        'type'=>'join',
                        'id'=>$user['id'],
//                    'room_num'=>$room_num,
                        'avatar'=>$user['avatar'],
                    ];
                    $msg=json_encode($msg);
                    Gateway::sendToGroup($msg_data['room_id'], $msg);
                }
                break;
            case 'leave':
                //离开房间
                Db::name('game')->where('user_id',$user['id'])
                    ->where('room_id',$msg_data['room_id'])->delete();
                //退出群组
                Gateway::leaveGroup($client_id,$msg_data['room_id']);
                //通知群组
                $msg=[
                    'type'=>'leave',
                    'id'=>$user['id'],
                    'avatar'=>$user['avatar'],
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'begin':
                //主持人开始游戏
                //看人数足不足
                $game=Db::name('game')->alias('g')
                    ->join('user u','g.user_id=u.id','left')
                    ->where('g.room_id',$msg_data['room_id'])
                    ->field('g.*,u.nickname,u.avatar')
                    ->select();
                $room=Db::name('room')->where('id',$msg_data['room_id'])->find();
                if(count($game)!=$room['number']){
                    $msg=[
                        'type'=>'error',
                        'msg'=>'房间人数不足',
                    ];
                    $msg=json_encode($msg);
                    Gateway::sendToClient($client_id, $msg);
                    break;
                }
                $flag=false;
                $name=[];
                //判断余额足不足
                foreach($game as $k=>$v){
                    $time=Db::name('time')->alias('t')
                        ->join('user u','t.user_id=u.id','left')
                        ->field('t.minute,u.nickname')
                        ->where('u.id',$v['user_id'])
                        ->where('t.shop_id',$user['shop_id'])
                        ->find();

                    if($time['minute']<30){
                        $msg=[
                            'type'=>'error',
                            'msg'=>'您当前账户余额不足，暂无法开始对局，请进行充值。',
                        ];
                        $flag=true;
                        $msg=json_encode($msg);
                        Gateway::sendToUid($v['user_id'], $msg);
                        $name[]=$time['nickname'];
                    }
                }
                if($name){
                    $name=implode(',',$name);
                    $msg=[
                        'type'=>'error',
                        'msg'=>'玩家“'.$name.'”账户时间不足无法开始对局，请提醒Ta充值',
                    ];
                    $flag=true;
                    $msg=json_encode($msg);
                    Gateway::sendToClient($client_id, $msg);
                }
                if($flag){
                    break;
                }
                //发身份-几号位
                $game=WorkerEvents::card($game,$room['role_list']);
                $msg=[];
                $msg['type']='game';
                $msg['game']=$game;
                //修改房间状态
                Db::name('room')->where('id',$msg_data['room_id'])->update(['status'=>'2','begintime'=>time()]);
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                $msg=[
                    'type'=>'beginSuccess',
                    'msg'=>'开始成功',
                    'begintime'=>time(),
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'speak' :
                //主持人 开始发言
                $msg=[
                    'type'=>'speak'
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'endSpeak' :
                //主持人 开始发言
                $msg=[
                    'type'=>'endSpeak'
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'voteStart':
                //开始投票
                $room=Db::name('room')->where('id',$msg_data['room_id'])->find();
                Db::name('room')->where('id',$msg_data['room_id'])->setInc('round');
                $game=Db::name('game')->alias('g')
                    ->join('user u','g.user_id=u.id','left')
                    ->join('role r','r.id=g.role_id','left')
                    ->where('g.room_id',$msg_data['room_id'])
                    ->field('g.*,u.nickname,u.avatar,r.name as role_name,r.image as role_image')
                    ->where('g.status','1')
                    ->order('g.room_number')
                    ->select();
                $msg=[
                    'type'=>'voteList',
                    'round'=>$room['round']+1,
                    'game'=>$game
                ];
                Db::name('game')->where('room_id',$msg_data['room_id'])->update(['vote'=>0]);
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'vote':
//                var_dump($msg_data);
                //投票
                Db::name('game')->where('room_id',$msg_data['room_id'])
                    ->where('user_id',$msg_data['user_id'])
                    ->setInc('vote','1');
                $msg=[
                    'type'=>'voteSucceed',
                    'msg'=>'投票成功',
                ];
                $msg=json_encode($msg);
                Gateway::sendToClient($client_id, $msg);
                //通知分组 票更新
                $msg=[
                    'type'=>'vote',
                    'msg'=>$user['id'],
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'voteList':
                //投票面板
                $data['data']=Db::name('game')->alias('g')
                    ->join('user u','g.user_id=u.id','left')
                    ->where('g.room_id',$msg_data['room_id'])
                    ->field('g.*,u.nickname,u.avatar')
                    ->select();
                $data['type']='voteResult';
                $msg=json_encode($data);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'endVote':
//                $data['data']=Db::name('game')
//                    ->where('status','1')
//                    ->where('room_id',$msg_data['room_id'])
//                    ->select();
                $data['msg']='投票结束';
                $data['type']='endVote';
                $msg=json_encode($data);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                //淘汰出局玩家
                $lose=Db::name('game')
                    ->where('status','1')
                    ->where('room_id',$msg_data['room_id'])
                    ->order('vote','desc')
                    ->limit('2')
                    ->select();
                //同票机制
                if($lose['0']['vote']>$lose['1']['vote']){
                    $data['data']=$lose['0'];
                    $data['type']='lose';
                    $msg=json_encode($data);
                    Gateway::sendToGroup($msg_data['room_id'], $msg);
                    Db::name('game')->where('room_id',$msg_data['room_id'])
                        ->where('user_id',$lose['0']['user_id'])->update(['status'=>'2']);
                }
                break;
            case 'out':
                $lose=Db::name('game')
                    ->where('status','1')
                    ->where('room_id',$msg_data['room_id'])
                    ->where('user_id',$msg_data['user_id'])
                    ->find();
                $data['data']=$lose;
                $data['type']='lose';
                Db::name('game')
                    ->where('status','1')
                    ->where('room_id',$msg_data['room_id'])
                    ->where('user_id',$msg_data['user_id'])
                    ->update(['status'=>'2']);
                $msg=json_encode($data);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'end':
                $data['win']=Db::name('game')->alias('g')
                    ->join('user u','g.user_id=u.id','left')
                    ->where('g.room_id',$msg_data['room_id'])
                    ->where('g.user_id','in',$msg_data['user_id'])
                    ->field('g.*,u.nickname,u.avatar')
                    ->select();
                $data['lose']=Db::name('game')->alias('g')
                    ->join('user u','g.user_id=u.id','left')
                    ->where('g.room_id',$msg_data['room_id'])
                    ->where('g.user_id','not in',$msg_data['user_id'])
                    ->field('g.*,u.nickname,u.avatar')
                    ->select();
                $data['type']='end';
                $msg=json_encode($data);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                //胜利积分
                $winScore=Config::get('site.win');
                $winPeo=explode(',',$msg_data['user_id']);
                Db::name('user')->where('id','in',$winPeo)->setInc('score',$winScore);
                Db::name('user')->where('id','in',$winPeo)->update(['updatetime'=>time()]);

                //失败积分
                $loseScore=Config::get('site.lose');
                $losePeo=Db::name('game')->where('room_id',$msg_data['room_id'])
                    ->where('user_id','not in',$winPeo)->column('user_id');
                Db::name('user')->where('id','in',$losePeo)
                    ->setInc('score',$loseScore);
                Db::name('user')->where('id','in',$losePeo)->update(['updatetime'=>time()]);
                //扣除时长
                $room=Db::name('room')->where('id',$msg_data['room_id'])->find();
                $now=time();
                Db::name('room')->where('id',$msg_data['room_id'])->update(['endtime'=>$now]);
                $minute=intval(bcdiv(bcsub($now,$room['begintime']),'60'));
                $allPeo=Db::name('game')->where('room_id',$msg_data['room_id'])->column('user_id');
                $shop=Db::name('user')->where('id',$room['user_id'])->value('shop_id');
                Db::name('time')->where('user_id','in',$allPeo)->where('shop_id',$shop)
                    ->setDec('minute',$minute);
                Db::name('user')->where('id',$room['user_id'])->setInc('duration',$minute);
                //游戏记录
                //胜利记录
                foreach($winPeo as $k=>$v){
                    Db::name('game_log')->insert([
                        'user_id'=>$v,
                        'shop_id'=>$user['shop_id'],
                        'status'=>1,
                        'minute'=>$minute,
                        'createtime'=>time()
                    ]);
                }
                //失败记录
                foreach($losePeo as $k=>$v){
                    Db::name('game_log')->insert([
                        'user_id'=>$v,
                        'shop_id'=>$user['shop_id'],
                        'minute'=>$minute,
                        'createtime'=>time()
                    ]);
                }
                //主持记录
                Db::name('direct_log')->insert([
                    'user_id'=>$user['id'],
                    'shop_id'=>$user['shop_id'],
                    'win_user_id'=>$msg_data['user_id'],
                    'minute'=>$minute,
                    'createtime'=>time()
                ]);
                //结束房间
                Db::name('room')->where('id',$msg_data['room_id'])->update(['status'=>'3']);
                break;
            case 'overtime':
                $winPeo=explode(',',$msg_data['user_id']);
                //加时
                Db::name('time') ->where('user_id','in',$winPeo)
                    ->where('shop_id',$user['shop_id'])
                    ->setInc('minute',$msg_data['minute']);
                Db::name('game_log')->where('shop_id',$user['shop_id'])
                    ->where('user_id','in',$winPeo)
                    ->where('status','1')
                    ->group('user_id,shop_id')
                    ->order('id','desc')
                    ->limit('1')
                    ->update(['overtime'=>$msg_data['minute']]);
                Db::name('direct_log')->where('user_id',$user['id'])
                    ->where('shop_id',$user['shop_id'])
                    ->order('id','desc')
                    ->limit('1')
                    ->update(['overtime'=>$msg_data['minute']]);
                $msg=[
                    'type'=>'overtime',
                    'msg'=>'加时成功',
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                break;
            case 'again':
                //修改房间状态
                Db::name('room')->where('id',$msg_data['room_id'])->update(['status'=>'1','round'=>'0','begintime'=>'','endtime'=>'']);
                //清除玩家
                Db::name('game')->where('room_id',$msg_data['room_id'])->delete();
                $msg=[
                    'type'=>'again',
                    'msg'=>'再来一局',
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                //取消分组
                Gateway::ungroup($msg_data['room_id']);
                break;
            case 'bye':
                Db::name('game')->where('room_id',$msg_data['room_id'])->delete();
                $msg=[
                    'type'=>'bye',
                    'msg'=>'结束',
                ];
                $msg=json_encode($msg);
                Gateway::sendToGroup($msg_data['room_id'], $msg);
                //取消分组
                Gateway::ungroup($msg_data['room_id']);
                break;
            default:
                $msg=[
                    'type'=>'boom',
                    'msg'=>'boom',
                ];
                $msg=json_encode($msg);
                Gateway::sendToClient($client_id, $msg);
                break;
        }
    }


    /**
     * 当用户断开连接时触发
     * @param $client_id
     * @return void
     * @throws \Exception
     */
    public static function onClose($client_id)
    {
        //离开房间
//        Db::name('game')->where('user_id',$user['id'])
//            ->where('room_id',$msg_data['room_id'])->delete();
//        //退出群组
//        Gateway::leaveGroup($client_id,$msg_data['room_id']);
        $uid=Gateway::getUidByClientId($client_id);
        if($uid){
            $room=Db::name('game')->where('user_id',$uid)->order('id','desc')->find();
            //退出群组
            Gateway::leaveGroup($client_id,$room['room_id']);
            if($room['status']!='2'){
                //游戏开始中就不删这个了
                Db::name('game')->where('user_id',$uid)->where('room_id',$room['room_id'])->delete();
            }
            $user=Db::name('user')->where('id',$uid)->find();
            $msg=[
                'type'=>'leave',
                'id'=>$user['id'],
                'avatar'=>$user['avatar'],
            ];
            $msg=json_encode($msg);
            //通知群组
            Gateway::sendToGroup($room['room_id'], $msg);
        }

//        break;

        // 向所有人发送
//        GateWay::sendToAll("$client_id 连接已断开\r\n");
    }

    public static function createUserMessage($msg_data, $content, $status): array
    {
        return [
            'uuid' => $msg_data['uuid'],
            'from_uid' => $msg_data['from_uid'],
            'to_uid' => $msg_data['to_uid'],
            'type' => "notice",
            'content' => $content,
            'record_time' =>  date('Y-m-d H:i', time()), // 格式化时间戳为年月日
            'status' => $status // 消息发送状态
        ];
    }

    public static function getGroup()
    {
        $group=Random::numeric(7);
        $res=Db::name('room')->where('room_group',$group)->find();
        if($res){
            WorkerEvents::getGroup();
        }
        return $group;
    }


    /**
     * @param $people
     * @param $role  1,2,3,4
     * @return void
     */
    public static function card($people,$role)
    {
        $role=explode(',',$role);
        $number=0;
        foreach($people as $k=>$v){
            $number=$number+1;
            $v['room_number']=$number;

//            var_dump($role);
            $key=array_rand($role);
            $v['role_id']=$role[$key];
            unset($role[$key]);
//            var_dump($v['role_id']);
            $ro=Db::name('role')->where('id',$v['role_id'])->find();
            $v['role_name']=$ro['name'];
            $v['image']=cdnurl($ro['image'],true);
            Db::name('game')->where('user_id',$v['user_id'])->update(['room_number'=>$v['room_number'],'role_id'=>$v['role_id']]);
            if($ro['type']=='2'){
                $v['friend']=true;
            }else{
                if($v['role_name']=='模仿鹅'){
                    $v['friend']=true;
                }else{
                    $v['friend']=false;
                }
            }
            $people[$k]=$v;
        }
        return $people;
    }


}